package blue.datacenter2;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;

public class SocketClient {
	private SocketChannel sock_channel_;
	private String ip_;
	private int port_;
	private String last_command_;  // Used to saved the last command.

	
	SocketClient(String ip, int port) throws IOException{
		ip_ = ip;
		port_ = port;
		ByteBuffer.allocate(512);
		last_command_ = null;
		
		System.out.println("Machine Connect to "+ip_+":"+port_);
		sock_channel_ = SocketChannel.open();
		sock_channel_.connect(new InetSocketAddress(ip_, port_));
	}

	public String read() throws IOException {
		String recv_str = null;
		try {
			ByteBuffer recv_buf = ByteBuffer.allocate(256);
			//recv_buf.clear();
			int recv_cnt = sock_channel_.read(recv_buf);
			if (recv_cnt>0) {
				recv_buf.flip();
				byte[] recv_bytes=new byte[recv_cnt];
				recv_buf.get(recv_bytes, 0, recv_cnt);
				recv_str = new String(recv_bytes,Charset.forName("UTF-8"));
				// recv success , it's meanings the last command is success, we need to clear last_command_.
				last_command_ = null;
			}
		}catch(IOException e) {
			e.printStackTrace();
		}
	    
		return recv_str;
	}

	public int write(String msg) throws IOException {
	    byte[] bytes = msg.getBytes( Charset.forName("UTF-8" ));
		ByteBuffer send_buf = ByteBuffer.allocate(256);
		//send_buf.clear();
		send_buf.put(bytes);
		send_buf.flip();
		last_command_ = msg;
		int send_cnt=0;
		synchronized(this){
			send_cnt = sock_channel_.write(send_buf);
		}

		return send_cnt;
	}

	public boolean reconnection() throws IOException {
		// Resend the last command.
		if (!sock_channel_.isConnected()) {
			// Reconnect
			System.out.println("Re-connect to Machine "+ip_+":"+port_);
			sock_channel_ = SocketChannel.open();
			sock_channel_.connect(new InetSocketAddress(ip_, port_));

			if(sock_channel_.isConnected()) {
				// Reconnec success
				if (last_command_!=null) {
					System.out.println("Re-write command > "+last_command_);
					synchronized(this){
						write(last_command_);
					}
				}
				return true;
			}
			return false;
		}

		return true;
	}

	public String getIP(){return ip_;}
	public int getPort(){return port_;}
}
